#ifndef _LIST_H_
#define _LIST_H_

#include <iostream>


template<class T>
class list {
	class link {
	public:
		T data;
		link *next,*prev;
		link (link *n, link *p, const T &d): next(n),prev(p),data(d) {}
		link () :next(0),prev(0){}
	};

	link head;
	link *curr;
	int num_elements;

	link* Search(const T &t) {
		link *p = head.next;
			while (p) {
				if (p->data == t) return p;
				p = p->next;
			}
		return 0;
	}

	public:
		list () : curr(0), num_elements(0) {};
		bool IsEmpty() {return head.next == 0;}
		bool Insert(const T &t);
		bool Delete(link *lnk);
		bool Delete(const T &t);	// true if managed to delete
		int ElementCount() {return num_elements;}
		~list () {while (head.next) Delete(head.next);}
		T** ArrayOfPElements(T **arr); //puts pointers to all the lists elements in arr. 		
		T* Get(const T &t) {return &(Search(t)->data);}
		bool GotoHead() {return change_and_check_curr(head.next);}
		bool GotoNext() {if( !curr) return false;
						return change_and_check_curr(curr->next);}
		bool GotoPrev() {if( !curr) return false;
						return change_and_check_curr(curr->prev);}
		bool CheckCurr() { return (curr!=0);}	// true if pointer is not NULL
		T& GetCurrData() {return curr->data;}


		bool change_and_check_curr(link *tmp){
//			if (!(this->CheckCurr())) return false;
			this->curr = tmp;
			if( this->curr ) return true;
			else return false;
		}

};



template<class T>
bool list<T>::Insert(const T &t) {
	link *tmp_link = Search(t);
	if (tmp_link) return false;
		tmp_link = new link(head.next,&head,t);
	if (head.next) head.next->prev = tmp_link;
	head.next = tmp_link;
	num_elements++;
	return true;
}

template<class T>
bool list<T>::Delete(link *lnk) {
	if (!lnk) return false;
		lnk->prev->next = lnk->next;
	if (lnk->next) lnk->next->prev = lnk->prev;
	if (curr == lnk) curr = curr->next;

	delete lnk;
	num_elements--;
	return true;
}


template<class T>
bool list<T>::Delete(const T &t) {
	link *tmp_link = Search(t);
	return Delete(tmp_link);
}


template<class T>
T** list<T>::ArrayOfPElements(T **arr) {
	link *tmp_link = head.next;
	int i=0;
	while (tmp_link) {
		arr[i++] = &(tmp_link->data);
		tmp_link = tmp_link->next;
	}

	return arr;
}


#endif

